﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using UpdaterForm.Annotations;

namespace UpdaterForm.CustomTreeView
{
    public class UpdateTreeView : INotifyPropertyChanged
    {

        #region Data

        bool? _isChecked = false;
        UpdateTreeView _parent;

        #endregion // Data

        #region Properties 

        public List<UpdateTreeView> Children { get; private set; }
        public bool IsInitiallySelected { get; private set; }

        public string Name { get; private set; }
        public string FullName { get; private set; }


        #region IsChecked

        /// <summary>
        /// Gets/sets the state of the associated UI toggle (ex. CheckBox).
        /// The return value is calculated based on the check state of all
        /// child FooViewModels.  Setting this property to true or false
        /// will set all children to the same check state, and setting it 
        /// to any value will cause the parent to verify its check state.
        /// </summary>
        public bool? IsChecked
        {
            get { return _isChecked; }
            set { this.SetIsChecked(value, true, true); }
        }

        void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
        {
            if (value == _isChecked)
                return;

            _isChecked = value;

            if (updateChildren && _isChecked.HasValue)
                this.Children.ForEach(c => c.SetIsChecked(_isChecked, true, false));

            if (updateParent && _parent != null)
                _parent.VerifyCheckState();

            this.OnPropertyChanged("IsChecked");
        }

        void VerifyCheckState()
        {
            bool? state = null;
            for (int i = 0; i < this.Children.Count; ++i)
            {
                bool? current = this.Children[i].IsChecked;
                if (i == 0)
                {
                    state = current;
                }
                else if (state != current)
                {
                    state = null;
                    break;
                }
            }
            this.SetIsChecked(state, false, true);
        }

        #endregion // IsChecked


        #endregion

        #region Create

        public static List<UpdateTreeView> LoadFromDirInfo(DirectoryInfo info)
        {
            var tree = new UpdateTreeView(info);
            tree.Initialize();
            tree.IsInitiallySelected = true;
            tree.IsChecked = true;
            return  tree.Children;
        }

        //TODO: navernoe mozno objedenit ispolzuemie polja DirInfo i Log v Update
        public static List<UpdateTreeView> LoadFromDirInfo(DirectoryInfo info,UpdateLog log)
        {
            var tree = new UpdateTreeView(info,log);
            tree.Initialize();
            return tree.Children;
        }
        
        UpdateTreeView(DirectoryInfo dir)
        {
            //TODO: Mozet sohranit dir kak property ? Eli nado bolwe info
            this.Name = dir.Name;
            this.Children = new List<UpdateTreeView>();
            //TODO: Mozet sdelat otdelnie classi dla failov i directori
            //TODO: LazyLoading mozet prigoditsa
            var subDirs = dir.GetDirectories();
            foreach (var subDir in subDirs){
                Children.Add(new UpdateTreeView(subDir));
            }

            var files = dir.GetFiles();
            foreach (var file in files)
                Children.Add(new UpdateTreeView(file.Name));
        }

        
        UpdateTreeView(DirectoryInfo dir,UpdateLog log)
        {
            this.Name = dir.Name;
            this.Children = new List<UpdateTreeView>();
            var subDirs = dir.GetDirectories();
            foreach (var subDir in subDirs){
                Children.Add(new UpdateTreeView(subDir));
            }

            var files = dir.GetFiles();
            foreach (var file in files)
            {
                var node = new UpdateTreeView(file.Name)
                {
                    IsChecked = log.TransferedFiles.Contains(file.FullName)
                };
                Children.Add(node);

            }
        }

        UpdateTreeView(string name)
        {
            this.Name = name;
            this.Children = new List<UpdateTreeView>();
        }

        void Initialize()
        {
            foreach (UpdateTreeView child in this.Children)
            {
                child._parent = this;
                child.Initialize();
            }
        }

        #endregion // Create

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        private System.IO.DirectoryInfo dir;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged(string propName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) 
                handler(this, new PropertyChangedEventArgs(propName));
        }

        #endregion
    }
}
